package com.ruibang.glass.portal.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.portal.constant.Constants;
import com.ruibang.glass.portal.constant.UserErrorCode;
import com.ruibang.glass.portal.entity.Meta;
import com.ruibang.glass.portal.entity.NewMenu;
import com.ruibang.glass.portal.mapper.NewMenuMapper;
import com.ruibang.glass.portal.mapper.RoleMenuMapper;
import com.ruibang.glass.portal.mapper.UserRoleMapper;
import com.ruibang.glass.portal.util.RSAEncrypt;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.model.ResultBody;
import io.seata.common.util.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: songJinKang
 * @CreateTime: 2023-10-18  16:28
 * @Description: TODO
 * @Version: 1.0
 */
@Service
public class NewMenuService extends ServiceImpl<NewMenuMapper, NewMenu> implements IService<NewMenu> {

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RedisSingleService redisService;

    @Autowired
    private RoleMenuService roleMenuService;

    /**
     * @Description: 保存菜单
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 16:34
     */
    public ResultBody saveMenu(NewMenu menu) {
        if (menu.getType().equals(Constants.STR_TWO) && menu.getParentId().equals(Constants.STR_ZERO)) {
            return ResultBody.fail(UserErrorCode.BTN_NOT_TOP.getCode(), UserErrorCode.BTN_NOT_TOP.getMsg());
        }
        //设置元数据
        if (menu.getMeta() != null) {
            menu.setMetaJson(JSONObject.toJSONString(menu.getMeta()));
        }
        //保存
        menu.setCreateTime(LocalDateTime.now());
        if (StringUtils.isNotBlank(menu.getPath())) {
            menu.setMenuId(RSAEncrypt.encryptByMD5(menu.getPath()));
        } else {
            menu.setMenuId(UUID.randomUUID().toString().replaceAll("-", ""));
        }

        this.save(menu);

        //放入缓存
        redisService.hset(RedisKey.MENU_GROUP_TYPE, menu.getMenuId(), menu.getName());
        return ResultBody.success();
    }


    /**
     * @Description: 修改菜单
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 16:38
     */
    public ResultBody edit(NewMenu menu) {
        if (StringUtils.isBlank(menu.getMenuId())) {
            return ResultBody.fail(UserErrorCode.PARAM_ERROR.getCode(), UserErrorCode.PARAM_ERROR.getMsg());
        }
        if (menu.getType().equals(Constants.STR_TWO) && menu.getParentId().equals(Constants.STR_ZERO)) {
            return ResultBody.fail(UserErrorCode.BTN_NOT_TOP.getCode(), UserErrorCode.BTN_NOT_TOP.getMsg());
        }
        if (menu.getMeta() != null) {
            menu.setMetaJson(JSONObject.toJSONString(menu.getMeta()));
        }

//        NewMenu oldMenu = this.getById(menu.getMenuId());
//        if(oldMenu!=null && StringUtils.isNotBlank(menu.getPath())){
//            if(!oldMenu.getPath().equals(menu.getPath())){
//                menu.setMenuId(RSAEncrypt.encryptByMD5(menu.getPath()));
//                menu.setCreateTime(LocalDateTime.now());
//                this.save(menu);
//                this.deleteByMenuId(menu.getMenuId());
//                return ResultBody.success();
//            }
//        }

        //修改
        menu.setUpdateTime(LocalDateTime.now());
        this.updateById(menu);
        //放入缓存
        redisService.hset(RedisKey.MENU_GROUP_TYPE, menu.getMenuId(), menu.getName());
        return ResultBody.success();
    }


    /**
     * @Description: 根据菜单id删除
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 16:41
     */
    public ResultBody deleteByMenuId(String menuId) {
        //判断是否还有子级
        Long count = lambdaQuery().eq(NewMenu::getParentId, menuId).count();
        if (count > 0) {
            return ResultBody.fail(UserErrorCode.MENU_IS_CHILDREN.getCode(), UserErrorCode.MENU_IS_CHILDREN.getMsg());
        }
        //删除
        this.removeById(menuId);
        //删除关联信息
        roleMenuMapper.delByMenuId(menuId);

        //放入缓存
        redisService.del(RedisKey.MENU_GROUP_TYPE, menuId);
        return ResultBody.success();
    }


    /**
     * @Description: 获取所有菜单树
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 16:44
     */
    public ResultBody queryMenuTree() {
        List<NewMenu> menus = this.list();
        if (CollectionUtils.isNotEmpty(menus)) {
            //反序列化元数据
            deserializeMeta(menus);
        }
        return ResultBody.success(getTree(menus));
    }

    /**
     * @Description: 转树结构
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 17:06
     */
    private List<NewMenu> getTree(List<NewMenu> menus) {
        if (CollectionUtils.isNotEmpty(menus)) {
            //获取顶级
            List<NewMenu> topNewMenus = menus.stream().filter(e -> e.getParentId().equals(Constants.STR_ZERO)).collect(Collectors.toList());
            //按钮
            Map<String, List<NewMenu>> btnMap = new HashMap<>(16);
            List<NewMenu> btnMenu = menus.stream().filter(e -> e.getType().equals(Constants.STR_TWO)).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(btnMenu)) {
                btnMap.putAll(btnMenu.stream().collect(Collectors.groupingBy(NewMenu::getParentId)));
            }
            //set子级
            if (CollectionUtils.isNotEmpty(topNewMenus)) {
                for (NewMenu topNewMenu : topNewMenus) {
                    setMenuChildren(topNewMenu, menus, btnMap);
                }
            }
            return topNewMenus.stream().sorted(Comparator.comparing(e -> e.getMeta().getOrder())).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }


    /**
     * @Description: 设置子级
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 16:57
     */
    private void setMenuChildren(NewMenu topNewMenu, List<NewMenu> menus, Map<String, List<NewMenu>> btnMap) {
        String menuId = topNewMenu.getMenuId();
        List<NewMenu> children = menus.stream().filter(e -> e.getParentId().equals(menuId) && !e.getType().equals(Constants.STR_TWO)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(children)) {
            topNewMenu.setChildren(children);
            for (NewMenu child : children) {
                //是否菜单
                if (child.getType().equals(Constants.STR_ONE)) {
                    //设置按钮
                    child.setBtns(btnMap.get(child.getMenuId()));
                }
                setMenuChildren(child, menus, btnMap);
            }
        }
    }


    /**
     * @Description: 根据用户id获取菜单树
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 17:25
     */
    public ResultBody getTreeByUserId(String userId) {
        if (StringUtils.isBlank(userId)) {
            return ResultBody.fail(UserErrorCode.PARAM_ERROR.getCode(), UserErrorCode.PARAM_ERROR.getMsg());
        }
        //用户id获取角色
        List<NewMenu> menus = baseMapper.getTreeByUserId(userId);
        menus = menus.stream().distinct().collect(Collectors.toList());
        //反序列化元数据
        deserializeMeta(menus);
        return ResultBody.success(getTree(menus));
    }

    /**
     * @Description: 根据角色id获取菜单树
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-18 17:25
     */
    public ResultBody getMenuByRoleId(String roleId) {
        if (StringUtils.isBlank(roleId)) {
            return ResultBody.fail(UserErrorCode.PARAM_ERROR.getCode(), UserErrorCode.PARAM_ERROR.getMsg());
        }
        return ResultBody.success(baseMapper.getMenuByRoleId(roleId));
    }

    /**
     * @Description: 反序列化元数据
     * @version v1.0
     * @author songJinKang
     * @date 2023-10-19 16:32
     */
    private void deserializeMeta(List<NewMenu> menus) {
        for (NewMenu menu : menus) {
            String metaJson = menu.getMetaJson();
            if (StringUtils.isNotBlank(metaJson)) {
                menu.setMeta(JSONObject.parseObject(metaJson, Meta.class));
            }
        }
    }

    public ResultBody getByUserId(String userId) {
        //获取用户角色
        List<String> roleIds = userRoleMapper.getRolesIdsByUserId(userId);
        if (CollectionUtils.isNotEmpty(roleIds)) {
            List<String> menuIds = roleMenuService.getByRoleIds(roleIds);
            //拿用户按钮
            return ResultBody.success(lambdaQuery().in(NewMenu::getMenuId, menuIds).eq(NewMenu::getType, Constants.TWO_STR).list());
        }
        return ResultBody.success();
    }

}
